package main

import (
	"bytes"
	"fmt"
	"golang.org/x/net/html"
	"gopkg.in/ini.v1"
	"log"
	"net/http"
	"os"
	"strings"
	"爬虫/Utils"
)

var listFind bool
var isCategory bool
var find bool // 寻找文章标志位

var serverUrl string
var novelPath string

func init() {
	cfg, err := ini.Load("appconfig.ini")
	if err != nil {
		fmt.Println("读取配置文件错误：", err)
		log.Fatal(err)
		os.Exit(1)
	}
	serverUrl = fmt.Sprint(cfg.Section("spider").Key("serverUrl"))
	novelPath = fmt.Sprint(cfg.Section("novelPath").Key("novelPath"))
}

func main() {
	doc, err := getPageNode(serverUrl)
	if err != nil {
		fmt.Println("读取body出错：", err)
		return
	}
	parseCategory(doc)
}

func getPageNode(url string) (*html.Node, error) {
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("http请求出错：", err)
		return nil, err
	}
	defer resp.Body.Close()
	doc, err := html.Parse(resp.Body)
	if err != nil {
		fmt.Println("读取body出错：", err)
		return nil, err
	}
	return doc, nil
}

/*//获取菜单列表
func findCategoryLink(doc *html.Node) {
	if doc.Type == html.ElementNode && doc.Data == "div" {
		for _, a := range doc.Attr {
			if a.Key == "class" && a.Val == "nav" {
				listFind = true
				parseTitle(doc)
				break
			}
		}
	}
	if !listFind {
		for c := doc.FirstChild; c != nil; c = c.NextSibling {
			findCategoryLink(doc)
		}
	}
}*/

//获取菜单列表
func parseCategory(n *html.Node) {
	if n.Type == html.ElementNode && n.Data == "a" {
		for _, a := range n.Attr {
			if a.Key == "href" && strings.Contains(a.Val, "xclass") {
				isCategory = true
				//获取文章title
				var novelCategory string
				var detailUrl string
				for c := n.FirstChild; c != nil; c = c.NextSibling {
					//buf.WriteString(c.Data+ "\n")
					novelCategory = c.Data
					detailUrl = serverUrl + a.Val
					//fmt.Println(c.Data, serverUrl, a.Val)
				}
				categoryPath := novelPath + "\\" + novelCategory
				filehelper.MakeDictionary(categoryPath)

				doc, err := getPageNode(detailUrl)
				if err != nil {
					fmt.Println("方法parseTitle执行getPageNode读取body出错：", err)
					return
				}
				//fmt.Println(novelCategory, detailUrl)
				parseBookList(doc, categoryPath)

				//url := a.Val
				//target := serverUrl + url // 得到 分类url
				//everyChapter(target)
				//num--
				break
			}
		}
	}
	//if !isCategory {
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		parseCategory(c)
	}
	//}
}

//获取菜单列表
func parseBookList(n *html.Node, path string) {
	if n.Type == html.ElementNode && n.Data == "span" {
		for _, a := range n.Attr {
			if a.Key == "class" && a.Val == "s2" {
				for c := n.FirstChild; c != nil; c = c.NextSibling {
					if c.Type == html.ElementNode && c.Data == "a" {
						for _, itm := range c.Attr {
							if itm.Key == "href" {
								var novelname string
								for category := c.FirstChild; category != nil; category = category.NextSibling {
									novelname = category.Data
								}
								//fmt.Println(novelname, itm.Val)
								bookUrl := serverUrl + itm.Val
								novelPath := path + "\\" + novelname + ".txt"
								ok, _ := filehelper.PathExists(novelPath)
								if !ok {
									f, _ := os.Create(path + "\\" + novelname + ".txt")
									f.Close()
								}
								Get_Book(bookUrl, novelPath)
							}
						}
						break
					}
					//fmt.Println("parseBookList", c.Data, serverUrl, a.Val)
				}
				break
			}
		}
	}
	//if !isCategory {
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		parseBookList(c, path)
	}
	//}
}

func Get_Book(target string, path string) error {
	fmt.Println("Get_Book", path, target)
	resp, err := http.Get(target)
	if err != nil {
		fmt.Println("get err http", err)
		return err
	}
	defer resp.Body.Close()
	doc, err := html.Parse(resp.Body)
	if err != nil {
		fmt.Println("html parse err", err)
		return err
	}
	bookfile, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0600)
	defer bookfile.Close()
	parseList(doc, path, bookfile)
	return nil
}

//找到文章列表
func parseList(n *html.Node, path string, bookfile *os.File) {
	fmt.Println("parseList", path)
	if n.Type == html.ElementNode && n.Data == "div" {
		for _, a := range n.Attr {
			if a.Key == "id" && a.Val == "list" {
				//listFind = true
				parseTitle(n, path,bookfile)
				break
			}
		}
	}
	//if !listFind {
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			parseList(c, path,bookfile)
		}
	//}
}

//获取文章头部
func parseTitle(n *html.Node, path string,bookfile *os.File) {
	if n.Type == html.ElementNode && n.Data == "a" {
		for _, a := range n.Attr {
			if a.Key == "href" {
				//获取文章title
				var title string
				for c := n.FirstChild; c != nil; c = c.NextSibling {
					title = c.Data + "\n\r"
				}
				url := a.Val
				target := serverUrl + url // 得到 文章url
				everyChapter(target, path, title,bookfile)
			}
		}
	}
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		parseTitle(c, path,bookfile)
	}
}

//获取每个章节
func everyChapter(target string, path string, title string,bookfile *os.File) {
	fmt.Println("everyChapter", target, path, title)
	var buf bytes.Buffer
	buf.WriteString(title)

	resp, err := http.Get(target)
	if err != nil {
		fmt.Println("get err http", err)
	}
	defer resp.Body.Close()
	doc, err := html.Parse(resp.Body)
	find = false
	parse(doc, path, title, &buf)

	if err != nil {
		fmt.Println("get create file err", err)
	}
	file := strings.NewReader(buf.String())
	//fmt.Println(title,fmt.Sprint(text))
	file.WriteTo(bookfile)

}

//解析文章
func parse(n *html.Node, path string, title string, buf *bytes.Buffer) {
	if n.Type == html.ElementNode && n.Data == "div" {
		for _, a := range n.Attr {
			if a.Key == "id" && a.Val == "content" {
				find = true
				parseTxt(buf, n, path, title)
				break
			}
		}
	}
	if !find {
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			parse(c, path, title, buf)
		}
	}
}

//提取文字
func parseTxt(buf *bytes.Buffer, n *html.Node, path string, title string) {
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		if c.Data != "br" {
			fmt.Println(c.Data)
			buf.WriteString(c.Data + "\n\r")
		}
	}
}
